#include "TrLoader.h"
#include <float.h>
#include <iostream>
#include <QDir>
#include <QDebug>
#include <QLibrary>
#include <QDateTime>
#include <QSettings>
#include <nlohmann/json.hpp>
#include "LogManager.h"
#include "Utils.hpp"


inline bool isOption(TThostFtdcProductClassType pClass)
{
    return pClass == THOST_FTDC_PC_Options || pClass == THOST_FTDC_PC_SpotOption ? true : false;
}

inline bool isFuture(TThostFtdcProductClassType pClass)
{
    return pClass == THOST_FTDC_PC_Futures;
}

using json = nlohmann::json;

TrLoader::TrLoader(QObject *parent) 
    : QObject(parent)
{
}

TrLoader::~TrLoader()
{
    release();
}

bool TrLoader::init(const QMap<QString, QVariant>& conf)
{
    if (m_initialized) {
        return true;
    }

    MLOG_DEBUG("loader", "Initializing TrLoader with config map");

    // 加载配置
    m_brokerID = conf["brokerID"].toString();
    m_userID = conf["userID"].toString();
    m_password = conf["password"].toString();
    m_authCode = conf["authCode"].toString();
    m_appID = conf["appID"].toString();
    m_frontAddr = conf["frontAddr"].toString();
    m_flowPath = conf["flowPath"].toString();
    m_modulePath = conf["module"].toString();
    m_mapPath = conf["mapPath"].toString();
    m_contractsPath = conf["contractsPath"].toString();

    // 检查必要的配置项
    if (m_userID.isEmpty() || m_password.isEmpty() || m_frontAddr.isEmpty() || m_modulePath.isEmpty()) {
        MLOG_ERROR("loader", "Missing required configuration");
        return false;
    }

    // 创建流文件目录
    QDir dir(m_flowPath);
    if (!dir.exists() && !dir.mkpath(".")) {
        MLOG_ERROR("loader", "Failed to create flow path: {}", m_flowPath.toStdString());
        return false;
    }

    // 加载品种映射信息
    if (!m_mapPath.isEmpty()) {
        if (!loadProductMapping(m_mapPath, m_productNameMap, m_productSessionMap)) {
            MLOG_ERROR("loader", "Failed to load product mapping");
            return false;
        }
        MLOG_INFO("loader", "Product mapping loaded successfully, {} entries", m_productNameMap.size());
    }

    // 加载CTP库
    if (!loadCtpLibrary()) {
        MLOG_ERROR("loader", "Failed to load CTP library");
        return false;
    }

    m_initialized = true;
    MLOG_DEBUG("loader", "TrLoader initialized successfully");
    return true;
}

bool TrLoader::loadConfig(const QString& configFile)
{
    QSettings settings(configFile, QSettings::IniFormat);
    settings.setIniCodec("UTF-8");

    if (settings.status() != QSettings::NoError) {
        MLOG_ERROR("loader", "Failed to load config file: {}", configFile.toStdString());
        return false;
    }

    // 读取CTP配置
    settings.beginGroup("CTP");
    m_brokerID = settings.value("BrokerID").toString();
    m_userID = settings.value("UserID").toString();
    m_password = settings.value("Password").toString();
    m_authCode = settings.value("AuthCode").toString();
    m_appID = settings.value("AppID").toString();
    m_frontAddr = settings.value("FrontAddr").toString();
    m_flowPath = settings.value("FlowPath").toString();
    m_modulePath = settings.value("Module").toString();
    settings.endGroup();

    // 读取文件路径配置
    settings.beginGroup("Files");
    m_mapPath = settings.value("MapPath").toString();
    m_contractsPath = settings.value("ContractsPath").toString();
    settings.endGroup();

    // 检查必要的配置项
    if (m_brokerID.isEmpty() || m_userID.isEmpty() || m_password.isEmpty() || 
        m_frontAddr.isEmpty() || m_modulePath.isEmpty()) {
        MLOG_ERROR("loader", "Missing required configuration items");
        return false;
    }

    return true;
}

void TrLoader::start()
{
    try {
        if (!m_initialized) {
            MLOG_ERROR("loader", "Not initialized");
            return;
        }

        if (m_pUserApi) {
            MLOG_WARN("loader", "Already started");
            return;
        }

        // 检查creator是否有效
        if (!m_creator) {
            MLOG_ERROR("loader", "CTP creator function is null");
            return;
        }

        // 创建CTP API实例
        MLOG_TRACE("loader", "Creating CTP API instance with flow path: {}", m_flowPath.toStdString());
        m_pUserApi = m_creator(m_flowPath.toStdString().c_str());
        if (!m_pUserApi) {
            MLOG_ERROR("loader", "Failed to create CTP API instance");
            return;
        }

        // 注册回调接口
        m_pUserApi->RegisterSpi(this);

        // 注册前置机地址
        MLOG_DEBUG("loader", "Registering front address: {}", m_frontAddr.toStdString());
        m_pUserApi->RegisterFront(const_cast<char*>(m_frontAddr.toStdString().c_str()));

        // 订阅私有流和公有流
        m_pUserApi->SubscribePrivateTopic(THOST_TERT_QUICK);
        m_pUserApi->SubscribePublicTopic(THOST_TERT_QUICK);

        // 初始化API
        MLOG_TRACE("loader", "Initializing CTP API");
        m_pUserApi->Init();

        emit started();
        MLOG_TRACE("loader", "TrLoader started successfully");
    }
    catch (const std::exception& e) {
        MLOG_ERROR("loader", "Exception in start: {}", e.what());
        if (m_pUserApi) {
            m_pUserApi->RegisterSpi(nullptr);
            m_pUserApi->Release();
            m_pUserApi = nullptr;
        }
        throw;
    }
}

void TrLoader::stop()
{
    if (m_pUserApi && m_loggedIn) {
        // 登出
        CThostFtdcUserLogoutField req{};
        strncpy(req.BrokerID, m_brokerID.toStdString().c_str(), sizeof(req.BrokerID) - 1);
        strncpy(req.UserID, m_userID.toStdString().c_str(), sizeof(req.UserID) - 1);
        m_pUserApi->ReqUserLogout(&req, ++m_requestID);
    }
    emit stopped();
}

void TrLoader::release()
{
    try {
        // 先释放API实例
        if (m_pUserApi) {
            m_pUserApi->RegisterSpi(nullptr);  // 取消回调注册
            m_pUserApi->Release();
            m_pUserApi = nullptr;
        }

        // 释放动态库
        if (m_library) {
            if (m_library->isLoaded()) {
                m_library->unload();
            }
            delete m_library;
            m_library = nullptr;
        }

        // 重置所有状态
        m_creator = nullptr;
        m_connected = false;
        m_loggedIn = false;
        m_authenticating = false;
        m_querying = false;
        m_initialized = false;

        MLOG_INFO("loader", "TrLoader released successfully");
    }
    catch (const std::exception& e) {
        MLOG_ERROR("loader", "Exception in release: {}", e.what());
    }
}

bool TrLoader::loadCtpLibrary()
{
    try {
        // 检查库文件是否存在
        QFileInfo fileInfo(m_modulePath);
        if (!fileInfo.exists()) {
            MLOG_ERROR("loader", "CTP library file not found: {}", m_modulePath.toStdString());
            return false;
        }

        MLOG_TRACE("loader", "Loading CTP library from: {}", m_modulePath.toStdString());

        // 如果已经有加载的库，先卸载
        if (m_library) {
            if (m_library->isLoaded()) {
                MLOG_INFO("loader", "Unloading existing library");
                m_library->unload();
            }
            delete m_library;
            m_library = nullptr;
        }

        // 创建新的库实例
        m_library = new QLibrary(m_modulePath);

        // 设置加载选项
        m_library->setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);

        // 加载动态库
        if (!m_library->load()) {
            MLOG_ERROR("loader", "Failed to load CTP library: {}", m_library->errorString().toStdString());
            delete m_library;
            m_library = nullptr;
            return false;
        }

        MLOG_TRACE("loader", "Successfully loaded CTP library");

        // 解析创建函数
        const char* creatorSymbol = nullptr;
#ifdef _WIN32
#ifdef _WIN64
        creatorSymbol = "?CreateFtdcTraderApi@CThostFtdcTraderApi@@SAPEAV1@PEBD@Z";
#else
        creatorSymbol = "?CreateFtdcTraderApi@CThostFtdcTraderApi@@SAPAV1@PBD@Z";
#endif
#else
        creatorSymbol = "_ZN19CThostFtdcTraderApi19CreateFtdcTraderApiEPKc";
#endif

        MLOG_TRACE("loader", "Resolving creator function with symbol: {}", creatorSymbol);
        m_creator = reinterpret_cast<CTPCreator>(m_library->resolve(creatorSymbol));

        if (!m_creator) {
            MLOG_ERROR("loader", "Failed to resolve CTP creator function: {}", m_library->errorString().toStdString());
            m_library->unload();
            delete m_library;
            m_library = nullptr;
            return false;
        }

        MLOG_DEBUG("loader", "Successfully resolved creator function");
        return true;
    }
    catch (const std::exception& e) {
        MLOG_ERROR("loader", "Exception in loadCtpLibrary: {}", e.what());
        if (m_library) {
            if (m_library->isLoaded()) {
                m_library->unload();
            }
            delete m_library;
            m_library = nullptr;
        }
        return false;
    }
}

void TrLoader::reqAuthenticate()
{
    if (!m_pUserApi || m_authenticating) {
        return;
    }

    CThostFtdcReqAuthenticateField req{};
    strncpy(req.BrokerID, m_brokerID.toStdString().c_str(), sizeof(req.BrokerID) - 1);
    strncpy(req.UserID, m_userID.toStdString().c_str(), sizeof(req.UserID) - 1);
    strncpy(req.AuthCode, m_authCode.toStdString().c_str(), sizeof(req.AuthCode) - 1);
    strncpy(req.AppID, m_appID.toStdString().c_str(), sizeof(req.AppID) - 1);

    m_authenticating = true;
    int ret = m_pUserApi->ReqAuthenticate(&req, ++m_requestID);
    if (ret != 0) {
        m_authenticating = false;
        emit error("认证请求发送失败", ret);
    }
}

void TrLoader::reqUserLogin()
{
    if (!m_pUserApi || m_loggedIn) {
        return;
    }

    CThostFtdcReqUserLoginField req{};
    strncpy(req.BrokerID, m_brokerID.toStdString().c_str(), sizeof(req.BrokerID) - 1);
    strncpy(req.UserID, m_userID.toStdString().c_str(), sizeof(req.UserID) - 1);
    strncpy(req.Password, m_password.toStdString().c_str(), sizeof(req.Password) - 1);

    int ret = m_pUserApi->ReqUserLogin(&req, ++m_requestID);
    if (ret != 0) {
        MLOG_ERROR("loader", "Login request failed, error code: {}", ret);
        emit error("登录请求发送失败", ret);
    }
}

void TrLoader::reqQryInstrument()
{
    if (!m_pUserApi || !m_loggedIn || m_querying) {
        return;
    }

    CThostFtdcQryInstrumentField req{};
    m_querying = true;
    int ret = m_pUserApi->ReqQryInstrument(&req, ++m_requestID);
    if (ret != 0) {
        m_querying = false;
        emit error("查询合约请求发送失败", ret);
    }
}

bool TrLoader::hasError(CThostFtdcRspInfoField *pRspInfo)
{
    return (pRspInfo && pRspInfo->ErrorID != 0);
}

QString TrLoader::getErrorMsg(CThostFtdcRspInfoField *pRspInfo)
{
    if (!pRspInfo) {
        return "Unknown error";
    }
    return QString::fromLocal8Bit(pRspInfo->ErrorMsg);
}

// CTP回调实现
void TrLoader::OnFrontConnected()
{
    m_connected = true;
    emit connected();
    MLOG_DEBUG("loader", "Connected to front server");

    // 如果配置了认证信息，先进行认证
    if (!m_authCode.isEmpty() && !m_appID.isEmpty()) {
        reqAuthenticate();
    } else {
        reqUserLogin();
    }
}

void TrLoader::OnRspAuthenticate(CThostFtdcRspAuthenticateField* pRspAuthenticateField, 
                                CThostFtdcRspInfoField* pRspInfo, 
                                int nRequestID, 
                                bool bIsLast)
{
    m_authenticating = false;
    
    if (hasError(pRspInfo)) {
        emit error(getErrorMsg(pRspInfo), pRspInfo->ErrorID);
        return;
    }

    MLOG_TRACE("loader", "Authentication successful");
    reqUserLogin();
}

void TrLoader::OnFrontDisconnected(int nReason)
{
    m_connected = false;
    m_loggedIn = false;
    emit disconnected(nReason);
    MLOG_WARN("loader", "Disconnected from front server, reason: {}", nReason);
}

void TrLoader::OnHeartBeatWarning(int nTimeLapse)
{
    emit heartbeatWarning(nTimeLapse);
    MLOG_WARN("loader", "Heartbeat warning, time lapse: {}", nTimeLapse);
}

void TrLoader::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, 
                             CThostFtdcRspInfoField *pRspInfo, 
                             int nRequestID, 
                             bool bIsLast)
{
    if (hasError(pRspInfo)) {
        emit loginFailed(getErrorMsg(pRspInfo));
        return;
    }

    m_loggedIn = true;
    QString msg = QString("登录成功 [%1]").arg(pRspUserLogin->TradingDay);
    emit loginSuccess(msg);
    MLOG_DEBUG("loader", "Login successful, trading day: {}", pRspUserLogin->TradingDay);

    // 登录成功后查询合约信息
    reqQryInstrument();
}

void TrLoader::OnRspUserLogout(CThostFtdcUserLogoutField *pUserLogout, 
                              CThostFtdcRspInfoField *pRspInfo, 
                              int nRequestID, 
                              bool bIsLast)
{
    m_loggedIn = false;
    
    if (hasError(pRspInfo)) {
        emit error(getErrorMsg(pRspInfo), pRspInfo->ErrorID);
        return;
    }

    QString msg = QString("登出成功 [%1]").arg(pUserLogout->UserID);
    emit logoutSuccess(msg);
    MLOG_INFO("loader", "Logout successful");
}

bool TrLoader::loadProductMapping(const QString& path, QMap<QString, QString>& name, QMap<QString, QString>& session) {
    if (path.isEmpty()) {
        MLOG_ERROR("loader", "Map file path is empty");
        return false;
    }
    QSettings mp(path, QSettings::IniFormat);
    mp.setIniCodec("utf-8");
    if (mp.status() != QSettings::NoError) {
        MLOG_ERROR("loader", "Load map file error: {}", path.toStdString());
        return false;
    }

    // 读取品种名称映射
    mp.beginGroup("Name");
    for(const QString& key : mp.allKeys()) {
        name[key] = mp.value(key).toString();
    }
    mp.endGroup();

    // 读取交易时间段映射，key格式为 {交易所ID}.{产品ID}
    mp.beginGroup("Session");
    for(const QString& key : mp.allKeys()) {
        session[key] = mp.value(key).toString();
    }
    mp.endGroup();

    MLOG_DEBUG("loader", "Loaded {} product names and {} sessions", 
               name.size(), session.size());
    return true;
}

// 添加一个辅助函数来从合约代码中提取品种代码
QString extractProductId(const char* instrumentID) {
    QString result;
    for (const char* p = instrumentID; *p != '\0'; ++p) {
        if (std::isalpha(*p)) {  // 只保留字母
            result.append(*p);
        }
    }
    return result;
}

void TrLoader::OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, 
                                 CThostFtdcRspInfoField *pRspInfo, 
                                 int nRequestID, 
                                 bool bIsLast)
{
    if (hasError(pRspInfo)) {
        m_querying = false;
        emit error(getErrorMsg(pRspInfo), pRspInfo->ErrorID);
        return;
    }

    if (pInstrument && isFuture(pInstrument->ProductClass)) {
        try {
            // 从合约代码中提取品种代码
            QString productId = extractProductId(pInstrument->InstrumentID);          
            // 构造session查找的key: {交易所ID}.{产品ID}
            QString sessionKey = QString("%1.%2").arg(
                QString(pInstrument->ExchangeID),
                productId
            );
            
            // 构造合约信息
            nlohmann::json contractJson;
            contractJson["code"] = pInstrument->InstrumentID;
            contractJson["exchg"] = pInstrument->ExchangeID;
            contractJson["name"] = QString("%1%2").arg(
                m_productNameMap.value(productId, productId),
                QString(pInstrument->InstrumentID).right(3)
            ).toStdString();
            contractJson["product"] = productId.toStdString();
            contractJson["session"] = m_productSessionMap.value(sessionKey, "").toStdString();
            if(contractJson["session"].empty()) {
                MLOG_WARN("loader", "No session found for instrument: {}", pInstrument->InstrumentID);
                return;
            }
            
            // 交易限制
            contractJson["maxmarketqty"] = Utils::check_v(pInstrument->MaxMarketOrderVolume);
            contractJson["maxlimitqty"] = Utils::check_v(pInstrument->MaxLimitOrderVolume);
            contractJson["minmarketqty"] = Utils::check_v(pInstrument->MinMarketOrderVolume);
            contractJson["minlimitqty"] = Utils::check_v(pInstrument->MinLimitOrderVolume);
            
            // 日期信息
            contractJson["opendate"] = QString(pInstrument->OpenDate).trimmed().toStdString();
            contractJson["expiredate"] = QString(pInstrument->ExpireDate).trimmed().toStdString();
            
            // 保证金率
            contractJson["longmarginratio"] = Utils::check_v(pInstrument->LongMarginRatio);
            contractJson["shortmarginratio"] = Utils::check_v(pInstrument->ShortMarginRatio);
            
            // 价格和数量信息
            contractJson["pricetick"] = Utils::check_v(pInstrument->PriceTick);
            contractJson["volumemultiple"] = Utils::check_v(pInstrument->VolumeMultiple);
            contractJson["strikeprice"] = Utils::check_v(pInstrument->StrikePrice);
            
            // 将合约信息添加到总的JSON对象中
            m_contractsJson[pInstrument->InstrumentID] = contractJson;
        }
        catch (const std::exception& e) {
            MLOG_ERROR("loader", "Error processing instrument {}: {}", 
                      pInstrument->InstrumentID, e.what());
        }
    }

    if (bIsLast) {
        m_querying = false;
        
        try {
            // 直接保存到contracts.json
            QFile file(m_contractsPath);
            if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
                QTextStream out(&file);
                out << QString::fromStdString(m_contractsJson.dump(4));
                file.close();
                MLOG_INFO("loader", "Successfully saved {} contracts to {}", 
                         m_contractsJson.size(), m_contractsPath.toStdString());
            } else {
                MLOG_ERROR("loader", "Failed to write to {}", m_contractsPath.toStdString());
            }
        }
        catch (const std::exception& e) {
            MLOG_ERROR("loader", "Error saving {}: {}", m_contractsPath.toStdString(), e.what());
        }
        
        emit instrumentsUpdated();
        MLOG_DEBUG("loader", "Instruments query completed");
    }
}
